package cn.wizzer.app.task.commons.ext.quartz.job;

import cn.wizzer.app.sys.modules.models.SysErcAddress;
import cn.wizzer.app.sys.modules.models.SysParam;
import cn.wizzer.app.sys.modules.services.SysErcAddressService;
import cn.wizzer.app.sys.modules.services.SysParamService;
import cn.wizzer.app.sys.modules.services.SysTaskService;
import cn.wizzer.app.user.modules.models.UserRecharge;
import cn.wizzer.app.user.modules.models.enums.PayChannel;
import cn.wizzer.app.user.modules.models.enums.RechargeStatusEnum;
import cn.wizzer.app.user.modules.services.account.UserRechargeService;
import cn.wizzer.framework.util.HttpUtil;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.ioc.loader.annotation.Inject;
import org.nutz.ioc.loader.annotation.IocBean;
import org.nutz.lang.Strings;
import org.nutz.lang.Times;
import org.nutz.log.Log;
import org.nutz.log.Logs;
import org.quartz.Job;
import org.quartz.JobExecutionContext;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Comparator;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@IocBean
public class RechargeOrderJob implements Job {

    private static final Log log = Logs.get();
    @Inject
    @Reference
    private UserRechargeService rechargeService;
    @Inject
    @Reference
    private SysParamService sysParamService;

    @Inject
    @Reference
    private SysTaskService sysTaskService;

    @Inject
    @Reference
    private SysErcAddressService sysErcAddressService;

    @Override
    public void execute(JobExecutionContext context) throws RuntimeException {
        //改为已取消
        rechargeService.update(Chain.make("status", RechargeStatusEnum.CANCELLED).add("cancelAt", Times.getTS()),
                //待确认（未确认转账）
                Cnd.where("status", "=", RechargeStatusEnum.PAYING)
                        //订单创建超过半小时
                        .and("ctAt", "<=", System.currentTimeMillis() / 1000 - (60 * 30)));


        // 超过30分钟的USDT充值订单取消掉
        rechargeService.update(Chain.make("status", RechargeStatusEnum.CANCELLED).add("cancelAt", Times.getTS()),
                //待确认（未确认转账）
                Cnd.where("status", "=", RechargeStatusEnum.PAID)
                        //订单创建超过半小时
                        .and("channel", "=", PayChannel.ERC20)
                        .and("ctAt", "<", System.currentTimeMillis() / 1000 - (60 * 30)));

        //region ERC20渠道充值单审核--30min内
        List<UserRecharge> query = rechargeService.query(Cnd.where("status", "=", RechargeStatusEnum.PAID).and("channel", "=", PayChannel.ERC20)
                .and("ctAt", ">=", System.currentTimeMillis() / 1000 - (60 * 30)));
        if (query.size() > 0) {
            SysParam sysParam = sysParamService.fetch();
            for (SysErcAddress ercAddress : sysErcAddressService.allUseful()) {

                String tokenTxUrl = String.format("%sapi?module=account&action=tokentx&address=%s&startblock=0&endblock=999999999&sort=desc&apikey=%s",
                        //baseUrl
                        sysParam.getErcUrl(),
                        //address
                        ercAddress.getAddress(),
                        //apiKey
                        sysParam.getErcApiKey());
                String body = null;
                try {
                    body = HttpUtil.createRequest()
                            .setUrl(tokenTxUrl)
                            .send()
                            .getBody();
                } catch (IOException e) {
                    log.error(e);
                }
                JSONArray result = JSONObject.parseObject(body)
                        .getJSONArray("result");
                Long timeCondition = query.stream().min(Comparator.comparing(UserRecharge::getCtAt)).get().getCtAt();
                List<JSONObject> transactions = result.stream()
                        .map(obj -> (JSONObject) JSON.toJSON(obj))
                        //最早一笔未处理订单时间之后的数据
                        .filter(jsonObject -> jsonObject.getLong("timeStamp") >= timeCondition)
                        .collect(Collectors.toList());
                query.forEach(userRecharge -> {
                    //金额判断
                    BigDecimal amount = userRecharge.getAmount();
                    Optional<JSONObject> transactionOptional = transactions.stream()
                            .filter(jsonObject -> amount.compareTo(jsonObject.getBigDecimal("value").divide(new BigDecimal(1000000))) == 0
                                    && jsonObject.getString("to").toLowerCase().equals(ercAddress.getAddress().toLowerCase()))
                            .findFirst();
                    if (transactionOptional.isPresent()) {
                        JSONObject transaction = transactionOptional.get();
                        // 区块交易ID
                        String hashId = transaction.getString("hash");
                        List<UserRecharge> hashList = rechargeService.query(Cnd.where("outNo", "=", hashId));
                        // 如果不存在则进行更新到账
                        if (hashList == null || hashList.size() == 0) {
                            rechargeService.update(Chain.make("outNo", transaction.getString("hash")), Cnd.where("id", "=", userRecharge.getId()));
                            rechargeService.examine(userRecharge.getId(), true, "RechargeOrderJob", "MANUAL", "sysTask");
                        }
                    }
                });
            }
        }
        //endregion


        // 处理 TRC20的订单

        String taskId = context.getJobDetail().getKey().getName();
        sysTaskService.update(Chain.make("exeAt", (int) (System.currentTimeMillis() / 1000))
                .add("exeResult", "执行成功"), Cnd.where("id", "=", taskId));
    }
}
